package hn.cch.netty.aop;

import hn.cch.netty.anno.Check;
import hn.cch.netty.anno.Valid;
import hn.cch.netty.param.ParamClass;
import hn.cch.netty.request.HttpReqMsg;
import hn.cch.common.util.JsonUtil;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

@Component
@Aspect
@Order(5)
public class ParamAop {

    private Logger logger = LoggerFactory.getLogger(ParamAop.class);

//    ProceedingJoinPoint:Around
//    JoinPoint:Before|After
//     @Before("execution(* hn.cch.netty.api.*.api(..))")
    public void aop(JoinPoint joinPoint) {


        logger.info("ParamAop start");
        Object[] args = joinPoint.getArgs();
        HttpReqMsg httpReqMsg = null;
        byte[] bytes = null;
        for (int i = 0; i < args.length; i++) {
            if (args[i] instanceof HttpReqMsg) {
                httpReqMsg = (HttpReqMsg) args[i];
            }
            if (args[i] instanceof byte[]) {
                bytes = (byte[]) args[i];
            }
        }
        if (bytes == null) {
            logger.error("ParamAop error");
        }
        if (httpReqMsg == null) {
            logger.error("ParamAop error");
        }
        // 参数转化
//        格式：path|type
        String param = httpReqMsg.getGet().getPath() + "|" + httpReqMsg.getGet().getType();
        Object object = JsonUtil.toObject(bytes, ParamClass.params.get(param));



        /******************************************************/
//        Object result = null;
//        try {
//            result = joinPoint.proceed(new Object[]{httpReqMsg, bytes});
//        } catch (Throwable e) {
//            e.printStackTrace();
//            logger.error("ParamAop fail");
//        }
        /******************************************************/

        logger.info("ParamAop success");
    }


    /**
     * 获取参数进行校验：返回null表示校验通过
     *
     * @param cls
     * @param obj
     * @param fld
     * @return
     */
    public String ValidateClass(Class<?> cls, Object obj, Field[] fld) {
        for (int j = 0; j < fld.length; j++) {
            // 对需要校验的参数进行校验
            Valid valid = fld[j].getAnnotation(Valid.class);// 获取方法参数（实体）的field上的注解Check
            if (valid != null) {
                String checkResult = validateField(valid, fld[j], obj);
                // 参数不符合规定
                if (checkResult != null) {
                    return checkResult;
                }

            }

            // 对标记为嵌套类的 进行递归校验
            Check check = fld[j].getAnnotation(Check.class);// 获取方法参数（实体）的field上的注解Valid
            if (check != null) {
                try {
                    Class<?> classx = fld[j].getType();
                    Method method = cls.getMethod("get" + fld[j].getName());
                    Object object = method.invoke(obj);
                    Field[] fields = classx.getDeclaredFields();
                    String checkResult = ValidateClass(classx, object, fields);
                    return checkResult;
                } catch (Exception e) {
                    e.printStackTrace();
                    logger.error("参数校验出错:" + e.getLocalizedMessage());
                    return e.getMessage();
                }
            }
        }
        return null;
    }

    /**
     * 进行具体参数校验：返回null表示校验通过
     *
     * @param valid
     * @param field
     * @param object
     * @return
     * @throws Exception
     */
    public String validateField(Valid valid, Field field, Object object) {
        try {
            // 设置属性可见
            field.setAccessible(true);
            // 获取field长度
            int length = 0;
            if (field.get(object) != null) {
                length = (String.valueOf(field.get(object))).length();
            }
            if (valid.notNull()) {
                if (field.get(object) == null || "".equals(String.valueOf(field.get(object)))) {
                    return "参数[" + field.getName() + "]不存在或者为空";
                }
            }

            if (valid.maxLen() > 0 && (length > valid.maxLen())) {
                return "参数[" + field.getName() + "]长度不能大于" + valid.maxLen();
            }

            if (valid.minLen() > 0 && (length < valid.minLen())) {
                return "参数[" + field.getName() + "]长度不能小于" + valid.minLen();
            }
            return null;
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("参数校验出错:" + e.getLocalizedMessage());
            return e.getMessage();
        }

    }

}
